package com.lyncs.ods.modules.txn.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.collect.Lists;
import com.lyncs.ods.common.api.CommonPage;
import com.lyncs.ods.common.web.RequestHolder;
import com.lyncs.ods.constant.LyncsOdsConstant;
import com.lyncs.ods.constant.TagInfoEnum;
import com.lyncs.ods.modules.company.model.CompanyInfo;
import com.lyncs.ods.modules.company.service.CompanyInfoService;
import com.lyncs.ods.modules.company.service.CompanyUserRoleService;
import com.lyncs.ods.modules.goods.model.SkuDetail;
import com.lyncs.ods.modules.goods.model.SkuInfo;
import com.lyncs.ods.modules.goods.service.SkuDetailService;
import com.lyncs.ods.modules.goods.service.SkuInfoService;
import com.lyncs.ods.modules.msg.service.MessageService;
import com.lyncs.ods.modules.txn.model.*;
import com.lyncs.ods.modules.txn.service.*;
import com.lyncs.ods.modules.user.service.CompanyUserRelationService;
import com.lyncs.ods.req.ListPageSearchReq;
import com.lyncs.ods.req.SaveOrderReq;
import com.lyncs.ods.resp.*;
import com.lyncs.ods.utils.ParamCheckUtil;
import com.lyncs.ods.utils.TxnCommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author alex
 * @date 2022/2/5 22:45
 * @description
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private TxnSkuDetailService txnSkuDetailService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private CompanyInfoService companyInfoService;
    @Autowired
    private TxnEditLogService txnEditLogService;
    @Autowired
    private CompanyUserRelationService companyUserRelationService;
    @Autowired
    private SkuDetailService skuDetailService;
    @Autowired
    private TxnOperateInfoService txnOperateInfoService;
    @Autowired
    private DeliverInfoService deliverInfoService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private CompanyUserRoleService companyUserRoleService;

    @Override
    public Long saveOrder(SaveOrderReq req) {
        OrderInfo dbOrder = null;
        OrderInfo orderInfo = new OrderInfo();
        String dbName = null;
        LocalDate dbDate = null;
        ParamCheckUtil.checkTxnOptions(req);
        if (req.getOrderId() == null) {
            //视为新增
            orderInfo = new OrderInfo().setId(IdUtil.getSnowflakeNextId())
                    .setSellerId(req.getSellerId())
                    .setBuyerId(req.getBuyerId())
                    .setCurrency(req.getCurrency())
                    .setCreateTime(RequestHolder.getRequestDateTime())
                    .setCreator(RequestHolder.getUserId())
                    .setCreatorCompanyId(RequestHolder.getCompanyId())
                    .setStatus(LyncsOdsConstant.OrderStatus.INIT.getKey());
        } else {
            //表示修改
            dbOrder = orderInfoService.getOneById(req.getOrderId());
            dbName = dbOrder.getOrderName();
            dbDate = dbOrder.getStartDate();
            BeanUtils.copyProperties(dbOrder, orderInfo);
        }
        if (req.getOperateType() == 1) {
            orderInfo.setStatus(LyncsOdsConstant.OrderStatus.DRAFT.getKey());
        } else if (LyncsOdsConstant.OrderStatus.DRAFT.getKey().equals(orderInfo.getStatus())) {
            orderInfo.setStatus(LyncsOdsConstant.OrderStatus.INIT.getKey());
        }
        Function<List<OrderInfo>, Map<Long, CompanyShortInfoResp>> companyInfoFunc = (list) -> companyInfoService.getTxnCompanyRespInfos(list);
        String orderName = TxnCommonUtils.buildTicketName(
                orderInfoService.lambdaQuery().setEntityClass(OrderInfo.class).ne(OrderInfo::getStatus, LyncsOdsConstant.OrderStatus.DELETED.getKey()),
                companyInfoFunc, LyncsOdsConstant.TxnType.ORDER, orderInfo,
                req.getStartDate(), dbDate, req.getOrderName(), dbName);
        orderInfo.setOrderName(orderName)
                .setStartDate(req.getStartDate())
                .setEstimatedDeliveryTime(req.getEstimatedDeliveryTime() == null ? null : req.getEstimatedDeliveryTime().atTime(LocalTime.MIN))
                .setCategoryCount(req.getSkuInfoList().size())
                .setRemark(req.getRemark())
                .setLastUpdater(RequestHolder.getUserId())
                .setUpdateTime(RequestHolder.getRequestDateTime())
                .setDestinationPort(req.getDestinationPort())
                .setPacking(req.getPacking())
                .setShippingMarks(req.getShippingMarks())
                .setTradingTerms(req.getTradingTerms())
                .setPaymentTerms(req.getPaymentTerms())
                .setShipment(req.getShipment())
                .setLoadingPort(req.getLoadingPort())
                .setTransshipmentPort(req.getTransshipmentPort())
                .setCustomFields(req.getCustomFields())
                .setAttachment(req.getAttachment());
        Long logId = IdUtil.getSnowflakeNextId();
        saveLog(dbOrder, orderInfo, logId);
        saveSku(req, orderInfo, logId);
        orderInfoService.saveOrUpdate(orderInfo);
        handleDeliverInfo(orderInfo);
        if (req.getOperateType() != 1 && req.getOrderId() != null) {
            orderInfoService.updateOrderStatus(List.of(req.getOrderId()));
        }
        OrderInfo finalOrderInfo = orderInfo;
        BiConsumer<CompanyInfo, CompanyInfo> emailNotifyFunc = (companyInfo, invitedCompanyInfo) -> messageService.shareTicketByEmail(req.getOrderId() == null, LyncsOdsConstant.TxnType.ORDER, finalOrderInfo.getId(), companyInfo, invitedCompanyInfo, companyInfoService.getNotifyEmail(finalOrderInfo));
        BiConsumer<CompanyInfo, CompanyInfo> smsNotifyFunc = (companyInfo, invitedCompanyInfo) -> messageService.shareTicketBySms(req.getOrderId() == null, LyncsOdsConstant.TxnType.ORDER, finalOrderInfo.getId(), companyInfo, invitedCompanyInfo.getId(), companyInfoService.getNotifyPhone(finalOrderInfo));
        Function<List<Long>, Map<Long, CompanyInfo>> companyFunc = (list) -> companyInfoService.getAvailableCompanyInfos(list).stream().collect(Collectors.toMap(CompanyInfo::getId, o -> o));
        TxnCommonUtils.notify(orderInfo, companyFunc, emailNotifyFunc, smsNotifyFunc);
        return finalOrderInfo.getId();
    }

    private void saveSku(SaveOrderReq req, OrderInfo orderInfo, Long logId) {
        List<TxnSkuDetail> details = new ArrayList<>();
        if (req.getOrderId() != null) {
            details = txnSkuDetailService.getTxnSkuDetail(req.getOrderId(), null, Boolean.TRUE);
        }
        //删除后重新添加的skuId
        List<TxnSkuDetail> revertSkus = new ArrayList<>();
        Triple<List<TxnSkuDetail>, List<Long>, List<Pair<TxnSkuDetail, TxnSkuDetail>>> orderDiffSkuTriple = TxnCommonUtils.getOrderDiffSkus(orderInfo.getId(), req.getSkuInfoList(), details, revertSkus);
        List<TxnSkuDetail> newOrderSkus = orderDiffSkuTriple.getLeft();
        List<Long> delSkuIds = orderDiffSkuTriple.getMiddle();
        List<Pair<TxnSkuDetail, TxnSkuDetail>> updateOrderSkus = orderDiffSkuTriple.getRight();
        if (CollectionUtil.isNotEmpty(newOrderSkus)) {
            txnSkuDetailService.saveBatch(newOrderSkus);
        }
        if (CollectionUtil.isNotEmpty(delSkuIds)) {
            txnSkuDetailService.lambdaUpdate().eq(TxnSkuDetail::getOrderId, req.getOrderId())
                    .isNull(TxnSkuDetail::getDeliverId)
                    .in(TxnSkuDetail::getSkuId, delSkuIds)
                    .set(TxnSkuDetail::getStatus, LyncsOdsConstant.OrderStatus.DELETED.getKey())
                    .update();
            handleOrderSkuDelete(req.getOrderId(), delSkuIds);
        }
        if (CollectionUtil.isNotEmpty(updateOrderSkus)) {
            txnSkuDetailService.updateBatchById(updateOrderSkus.stream().map(Pair::getRight).collect(Collectors.toList()));
        }
        if (CollectionUtils.isNotEmpty(revertSkus)) {
            List<TxnSkuDetail> updateList = new ArrayList<>();
            List<Long> revertSkuIds = revertSkus.stream().map(TxnSkuDetail::getSkuId).collect(Collectors.toList());
            List<TxnSkuDetail> deliverSkuDetails = txnSkuDetailService.lambdaQuery()
                    .eq(TxnSkuDetail::getOrderId, req.getOrderId())
                    .isNotNull(TxnSkuDetail::getDeliverId)
                    .in(TxnSkuDetail::getSkuId, revertSkuIds)
                    .list();
            if (CollectionUtils.isEmpty(deliverSkuDetails)) {
                updateList.addAll(revertSkus);
            } else {
                //恢复订单sku已经进行过交付时，还原状态
                Map<Long, List<TxnSkuDetail>> skuDeliveredMap = deliverSkuDetails.stream().collect(Collectors.groupingBy(TxnSkuDetail::getSkuId));
                revertSkus.forEach(txn -> {
                    if (skuDeliveredMap.containsKey(txn.getSkuId())) {
                        List<TxnSkuDetail> deliveredSkus = skuDeliveredMap.get(txn.getSkuId());
                        BigDecimal deliveredCount = deliveredSkus.stream().map(TxnSkuDetail::getDeliveredCount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal totalCount = txn.getTotalCount();
                        LyncsOdsConstant.TxnSkuStatus txnSkuStatus = deliveredCount.compareTo(totalCount) < 0 ? LyncsOdsConstant.TxnSkuStatus.PARTIAL_DELIVERY : LyncsOdsConstant.TxnSkuStatus.DELIVERED;
                        txn.setDeliveredCount(deliveredCount).setStatus(txnSkuStatus.getKey());
                        //删除原交付单sku的关联tag
                        updateList.addAll(deliveredSkus.stream().map(t -> new TxnSkuDetail().setId(t.getId()).setTagInfo(null)).collect(Collectors.toList()));
                    }
                    updateList.add(txn);
                });
            }
            txnSkuDetailService.updateBatchById(updateList);
        }
        saveLog(newOrderSkus, delSkuIds, updateOrderSkus, orderInfo.getId(), logId, req.getOrderId() == null);
    }

    public void saveLog(OrderInfo oldInfo, OrderInfo newInfo, Long logId) {
        txnEditLogService.saveLog(oldInfo, newInfo, LyncsOdsConstant.TxnType.ORDER, newInfo.getId(), logId, companyInfoService::getLoginCompanyName, companyUserRelationService::getLoginUserName);
    }

    public void saveLog(List<TxnSkuDetail> insertSubItems, List<Long> deleteSubItems, List<Pair<TxnSkuDetail, TxnSkuDetail>> updateSubItems, Long orderId, Long logId, boolean isNew) {
        LyncsOdsConstant.TxnEditType type = isNew ? LyncsOdsConstant.TxnEditType.ADD : LyncsOdsConstant.TxnEditType.EDIT;
        List<Long> skuIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(insertSubItems)) {
            skuIds.addAll(insertSubItems.stream().map(TxnSkuDetail::getSkuId).distinct().collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(updateSubItems)) {
            skuIds.addAll(updateSubItems.stream().map(Pair::getRight).map(TxnSkuDetail::getSkuId).distinct().collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(deleteSubItems)) {
            skuIds.addAll(deleteSubItems);
        }
        List<SkuInfo> skuInfos = skuInfoService.lambdaQuery().in(SkuInfo::getId, skuIds).list();
        Map<Long, String> skuNameMap = skuInfos.stream().collect(Collectors.toMap(SkuInfo::getId, SkuInfo::getName));
        txnEditLogService.saveSubItemLog(insertSubItems, deleteSubItems, updateSubItems, LyncsOdsConstant.TxnType.ORDER, type, LyncsOdsConstant.TxnType.SKU, orderId, logId, companyInfoService::getLoginCompanyName, companyUserRelationService::getLoginUserName, skuNameMap);
    }

    /**
     * 删除订单
     *
     * @param orderId orderId
     */
    @Override
    public void reverseOrder(Long orderId) {
        orderInfoService.lambdaUpdate()
                .eq(OrderInfo::getId, orderId)
                .set(OrderInfo::getStatus, LyncsOdsConstant.OrderStatus.DELETED.getKey())
                .set(OrderInfo::getTagInfo, TxnCommonUtils.getTagInfo(null, new TagInfo(TagInfoEnum.ORDER_DELETED), Boolean.FALSE))
                .update();
        txnSkuDetailService.lambdaUpdate().eq(TxnSkuDetail::getOrderId, orderId).isNull(TxnSkuDetail::getDeliverId).set(TxnSkuDetail::getStatus, LyncsOdsConstant.OrderStatus.DELETED.getKey()).update();
        handleOrderSkuDelete(orderId, null);
    }

    @Override
    public CommonPage<ListPageResp> listOrder(ListPageSearchReq req) {
        BiFunction<Long, Long, List<Long>> partnerFunc = (userId, companyId) -> companyUserRoleService.listAllAvailablePartnerId(userId, companyId);
        List<Long> topIdList = txnOperateInfoService.getTopTicket(RequestHolder.getCompanyId(), LyncsOdsConstant.TxnType.ORDER.getKey());
        LambdaQueryChainWrapper<OrderInfo> lambdaQueryChainWrapper = TxnCommonUtils.buildLambdaQueryWrapper(orderInfoService.lambdaQuery().setEntityClass(OrderInfo.class).ne(OrderInfo::getStatus, LyncsOdsConstant.OrderStatus.DELETED.getKey()), req, partnerFunc);
        Function<List<OrderInfo>, Map<String, String>> staffNameFunc = (list) -> companyUserRelationService.getCompanyUserName(list);
        Function<List<OrderInfo>, Map<Long, CompanyShortInfoResp>> companyInfoFunc = (list) -> companyInfoService.getTxnCompanyRespInfos(list);
        Function<List<Long>, List<TxnSkuDetailVO>> skuDetailFunc = (orderIdList) -> txnSkuDetailService.getDetails(orderIdList, null);
        return TxnCommonUtils.getListPageRespData(req, lambdaQueryChainWrapper, topIdList, skuDetailFunc, staffNameFunc, companyInfoFunc);
    }

    /**
     * get order detail info
     *
     * @param orderId orderId
     * @return order detail info
     */
    @Override
    public OrderDetailInfoResp getOrderDetail(Long orderId) {
        OrderInfo orderInfo = orderInfoService.getOneById(orderId);

        List<TxnSkuDetail> txnSkuDetails = txnSkuDetailService.getTxnSkuDetail(orderId, null);
        Set<Long> skuIds = txnSkuDetails.stream().map(TxnSkuDetail::getSkuId).collect(Collectors.toSet());
        List<SkuInfo> skuInfos = skuInfoService.lambdaQuery().in(SkuInfo::getId, skuIds).list();
        Map<Long, SkuInfo> skuInfoMap = skuInfos.stream().collect(Collectors.toMap(SkuInfo::getId, o -> o));

        List<SkuDetail> skuDetails = skuDetailService.lambdaQuery().in(SkuDetail::getSkuId, skuIds).list();
        Map<Long, Map<String, String>> skuAttrMap = skuInfoService.getSkuAttrs(skuDetails);

        Function<List<OrderInfo>, Map<Long, CompanyShortInfoResp>> companyInfoFunc = (list) -> companyInfoService.getTxnCompanyRespInfos(list);
        Map<Long, CompanyShortInfoResp> txnCompanyInfoMap = TxnCommonUtils.buildTxnCompanyInfo(companyInfoFunc, orderInfo);

        Map<Integer, Integer> skuCategoryMap = new HashMap<>() {{
            put(LyncsOdsConstant.OrderStatus.INIT.getKey(), 0);
            put(LyncsOdsConstant.OrderStatus.PARTIAL_DELIVERY.getKey(), 0);
            put(LyncsOdsConstant.OrderStatus.DELIVERED.getKey(), 0);
        }};
        txnSkuDetails.forEach(sku -> {
            Integer cnt = skuCategoryMap.get(sku.getStatus());
            skuCategoryMap.put(sku.getStatus(), ++cnt);
        });

        OrderDetailInfoResp resp = new OrderDetailInfoResp(orderInfo);
        resp.setDeliverCount(txnSkuDetailService.getOrderDeliverCount(orderId))
                .setTotalAmount(txnSkuDetails.stream().map(TxnSkuDetail::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString())
                .setSellerCompanyInfo(txnCompanyInfoMap.get(orderInfo.getSellerId()))
                .setBuyerCompanyInfo(txnCompanyInfoMap.get(orderInfo.getBuyerId()))
                .setCreatorName(companyUserRelationService.getCompanyUserName(orderInfo))
                .setUndeliveredCount(skuCategoryMap.get(LyncsOdsConstant.OrderStatus.INIT.getKey()))
                .setPartialCount(skuCategoryMap.get(LyncsOdsConstant.OrderStatus.PARTIAL_DELIVERY.getKey()))
                .setDeliveredCount(skuCategoryMap.get(LyncsOdsConstant.OrderStatus.DELIVERED.getKey()))
                .setTop(txnOperateInfoService.isTopTicket(RequestHolder.getCompanyIdAllowNull(), LyncsOdsConstant.TxnType.ORDER.getKey(), orderId));
        List<OrderDetailInfoResp.OrderSkuInfo> orderSkus = txnSkuDetails.stream().map(txnSkuDetail -> {
            SkuInfo thisSkuInfo = skuInfoMap.get(txnSkuDetail.getSkuId());
            return new OrderDetailInfoResp.OrderSkuInfo()
                    .setSkuId(thisSkuInfo.getId())
                    .setInnerCode(thisSkuInfo.getNo())
                    .setName(thisSkuInfo.getName())
                    .setTotalCount(txnSkuDetail.getTotalCount())
                    .setDeliveredCount(txnSkuDetail.getDeliveredCount())
                    .setTotalAmount(txnSkuDetail.getTotalAmount().toPlainString())
                    .setAmount(txnSkuDetail.getAmount().toPlainString())
                    .setUnit(thisSkuInfo.getUnit())
                    .setSkuAttrs(skuAttrMap.get(txnSkuDetail.getSkuId()))
                    .setTagInfos(JSONArray.parseArray(txnSkuDetail.getTagInfo(), TagInfo.class))
                    .setImgUrl(thisSkuInfo.getImgUrl())
                    .setRemark(txnSkuDetail.getRemark());
        }).collect(Collectors.toList());
        resp.setSkuInfoList(orderSkus);
        return resp;
    }

    @Override
    public void stickyOnTop(Long orderId, Integer type) {
        txnOperateInfoService.saveTopTicket(LyncsOdsConstant.TxnType.ORDER, orderId, type);
    }

    @Override
    public CommonPage<TxnEditLogResp> getOrderEditLog(Long orderId, Integer page, Integer pageSize) {
        return txnEditLogService.getEditLog(LyncsOdsConstant.TxnType.ORDER.getKey(), orderId, page, pageSize);
    }

    @Override
    public OrderDeliverLogResp getOrderSkuDeliverLog(Long orderId, Long skuId) {
        OrderDeliverLogResp orderDeliverLogResp = new OrderDeliverLogResp();
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        List<TxnSkuDetail> txnSkuDetails = txnSkuDetailService.lambdaQuery()
                .eq(TxnSkuDetail::getOrderId, orderId)
                //.isNotNull(TxnSkuDetail::getDeliverId)
                .eq(Objects.nonNull(skuId), TxnSkuDetail::getSkuId, skuId)
                .ne(TxnSkuDetail::getStatus, LyncsOdsConstant.TxnSkuStatus.DELETED.getKey())
                .list();
        if (CollectionUtil.isEmpty(txnSkuDetails)) {
            return orderDeliverLogResp;
        }
        Map<Boolean, List<TxnSkuDetail>> skuDetailMap = txnSkuDetails.stream().collect(Collectors.groupingBy(o -> o.getDeliverId() == null));
        List<TxnSkuDetail> orderSkuDetails = skuDetailMap.get(Boolean.TRUE);
        if (Objects.nonNull(skuId)) {
            SkuInfo skuInfo = skuInfoService.lambdaQuery().eq(SkuInfo::getId, skuId).one();
            List<SkuDetail> skuDetails = skuDetailService.lambdaQuery().eq(SkuDetail::getSkuId, skuId).list();
            Map<String, String> skuAttrMap = skuInfoService.getSkuAttrs(skuDetails).get(skuId);
            OrderDeliverLogResp.SkuInfo skuRespInfo = new OrderDeliverLogResp.SkuInfo();
            BeanUtils.copyProperties(skuInfo, skuRespInfo);
            skuRespInfo.setSkuId(skuId)
                    .setInnerCode(skuInfo.getNo())
                    .setSkuAttrs(skuAttrMap);
            TxnSkuDetail txnSkuDetail = orderSkuDetails.stream().filter(detail -> skuId.equals(detail.getSkuId())).findAny().orElse(null);
            if (Objects.isNull(txnSkuDetail)) {
                return orderDeliverLogResp;
            }
            skuRespInfo.setTotalCount(txnSkuDetail.getTotalCount()).setDeliveredCount(txnSkuDetail.getDeliveredCount()).setUndeliveredCount(txnSkuDetail.getTotalCount().subtract(txnSkuDetail.getDeliveredCount()));
            orderDeliverLogResp.setSkuInfo(skuRespInfo);
        }
        List<TxnSkuDetail> deliverSkuDetails = skuDetailMap.get(Boolean.FALSE);
        if (CollectionUtil.isEmpty(deliverSkuDetails)) {
            return orderDeliverLogResp;
        }
        Map<Long, Map<Long, TxnSkuDetail>> deliverSkuMap = deliverSkuDetails.stream().collect(Collectors.groupingBy(TxnSkuDetail::getDeliverId, Collectors.toMap(TxnSkuDetail::getSkuId, o -> o)));
        List<DeliverInfo> deliverInfos = deliverInfoService.lambdaQuery().in(DeliverInfo::getId, deliverSkuMap.keySet())
                .ne(DeliverInfo::getStatus, LyncsOdsConstant.DeliverStatus.DELETED.getKey())
                .ne(DeliverInfo::getStatus, LyncsOdsConstant.DeliverStatus.DRAFT.getKey())
                .list();
        Map<Long, CompanyShortInfoResp> txnCompanyRespInfoMap = companyInfoService.getTxnCompanyRespInfos(deliverInfos);

        orderDeliverLogResp.setSkuDeliverInfos(deliverInfos.stream().map(del -> {
            Map<Long, TxnSkuDetail> txnSkuDetailMap = deliverSkuMap.get(del.getId());
            List<Long> thisDeliverSkuIds = txnSkuDetailMap == null ? List.of() : Lists.newArrayList(txnSkuDetailMap.keySet());
            BigDecimal thisDeliverSkuAmount = txnSkuDetailMap == null ? BigDecimal.ZERO : txnSkuDetailMap.values().stream().map(TxnSkuDetail::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            DeliverShortInfoResp deliverShortInfoResp = new DeliverShortInfoResp()
                    .setDeliverId(del.getId())
                    .setOrderName(orderInfo.getOrderName())
                    .setSkuCount(thisDeliverSkuIds.size())
                    //交付历史统一取卖方企业信息
                    .setCompanyInfo(txnCompanyRespInfoMap.get(del.getSellerId()))
                    .setDeliverName(del.getDeliverName())
                    .setDeliverTime(del.getStartDate())
                    .setDeliverAmount(thisDeliverSkuAmount);
            //单个sku时返回tagInfo
            if (Objects.nonNull(skuId) && txnSkuDetailMap != null && txnSkuDetailMap.containsKey(skuId)) {
                deliverShortInfoResp.setTagInfos(JSONArray.parseArray(txnSkuDetailMap.get(skuId).getTagInfo(), TagInfo.class));
            }
            return deliverShortInfoResp;
        }).collect(Collectors.toList()));
        return orderDeliverLogResp;
    }

    private void handleDeliverInfo(OrderInfo orderInfo) {
        List<Integer> influencedStatus = List.of(LyncsOdsConstant.TxnSkuStatus.PARTIAL_DELIVERY.getKey(), LyncsOdsConstant.TxnSkuStatus.DELIVERED.getKey());
        if (orderInfo == null || !influencedStatus.contains(orderInfo.getStatus())) {
            return;
        }
        List<TxnSkuDetail> orderTxnSkus = txnSkuDetailService.lambdaQuery()
                .eq(TxnSkuDetail::getOrderId, orderInfo.getId())
                .isNull(TxnSkuDetail::getDeliverId)
                .in(TxnSkuDetail::getStatus, influencedStatus)
                .list();
        if (CollectionUtils.isEmpty(orderTxnSkus)) {
            return;
        }
        TagInfo tagInfo = new TagInfo(TagInfoEnum.SKU_OVER_DELIVERED);
        List<TxnSkuDetail> orderUpdateTxnSkus = new ArrayList<>();
        Map<Long, Boolean> deliverSkuTagMap = new HashMap<>();
        orderTxnSkus.forEach(txn -> {
            //当前sku已交付数量
            BigDecimal deliveredCount = txn.getDeliveredCount();
            BigDecimal totalCount = txn.getTotalCount();
            //未交付校验,用已交付数 或者 用状态判断
            if (BigDecimal.ZERO.equals(deliveredCount) ||
                    (totalCount.compareTo(deliveredCount) > 0 && LyncsOdsConstant.TxnSkuStatus.PARTIAL_DELIVERY.getKey().equals(orderInfo.getStatus())) ||
                    (deliveredCount.equals(totalCount) && LyncsOdsConstant.TxnSkuStatus.DELIVERED.getKey().equals(orderInfo.getStatus()))) {
                return;
            }
            LyncsOdsConstant.TxnSkuStatus txnSkuStatus = deliveredCount.compareTo(totalCount) < 0 ? LyncsOdsConstant.TxnSkuStatus.PARTIAL_DELIVERY : LyncsOdsConstant.TxnSkuStatus.DELIVERED;
            TxnSkuDetail txnSkuDetail = new TxnSkuDetail().setId(txn.getId()).setStatus(txnSkuStatus.getKey());
            //当前订单的sku总交付量改大了（改完后应为部分交付），且当前sku状态为部分交付
            if (totalCount.compareTo(deliveredCount) < 0 && LyncsOdsConstant.TxnSkuStatus.PARTIAL_DELIVERY.getKey().equals(orderInfo.getStatus())) {
                deliverSkuTagMap.put(txn.getSkuId(), Boolean.FALSE);
                txnSkuDetail.setTagInfo(TxnCommonUtils.getTagInfo(txn.getTagInfo(), tagInfo, Boolean.FALSE));
            }
            //当前订单的sku总交付量改小了（改完后应为已交付），且当前sku状态为已交付
            if (LyncsOdsConstant.TxnSkuStatus.DELIVERED.getKey().equals(orderInfo.getStatus()) && deliveredCount.compareTo(totalCount) > 0) {
                deliverSkuTagMap.put(txn.getSkuId(), Boolean.FALSE);
                txnSkuDetail.setTagInfo(TxnCommonUtils.getTagInfo(txn.getTagInfo(), tagInfo, Boolean.FALSE));
            }
            orderUpdateTxnSkus.add(txnSkuDetail);
        });
        //更新订单sku状态
        if (CollectionUtils.isNotEmpty(orderUpdateTxnSkus)) {
            txnSkuDetailService.updateBatchById(orderUpdateTxnSkus);
        }
        if (MapUtils.isNotEmpty(deliverSkuTagMap)) {
            List<TxnSkuDetail> deliverSkuList = txnSkuDetailService.lambdaQuery().eq(TxnSkuDetail::getOrderId, orderInfo.getId())
                    .isNotNull(TxnSkuDetail::getDeliverId)
                    .in(TxnSkuDetail::getSkuId, deliverSkuTagMap.keySet())
                    .eq(TxnSkuDetail::getStatus, LyncsOdsConstant.TxnSkuStatus.DELIVERED.getKey()).list();
            List<TxnSkuDetail> deliverSkuUpdateList = deliverSkuList.stream().map(txn -> new TxnSkuDetail().setId(txn.getId()).setTagInfo(TxnCommonUtils.getTagInfo(txn.getTagInfo(), tagInfo, deliverSkuTagMap.get(txn.getSkuId())))).collect(Collectors.toList());
            txnSkuDetailService.updateBatchById(deliverSkuUpdateList);
        }
    }

    private void handleOrderSkuDelete(@NotNull Long orderId, List<Long> skuIds) {
        TagInfoEnum tagInfoEnum = CollectionUtils.isNotEmpty(skuIds) ? TagInfoEnum.ORDER_SKU_DELETED : TagInfoEnum.ORDER_DELETED;
        TagInfo tagInfo = new TagInfo(tagInfoEnum);
        List<TxnSkuDetail> deliverSkuList = txnSkuDetailService.lambdaQuery().eq(TxnSkuDetail::getOrderId, orderId)
                //.isNotNull(TxnSkuDetail::getDeliverId)
                .in(CollectionUtils.isNotEmpty(skuIds), TxnSkuDetail::getSkuId, skuIds)
                .list();
        List<TxnSkuDetail> deliverSkuUpdateList = deliverSkuList.stream().map(txn -> new TxnSkuDetail().setId(txn.getId()).setTagInfo(TxnCommonUtils.getTagInfo(txn.getTagInfo(), tagInfo, Boolean.FALSE))).collect(Collectors.toList());
        txnSkuDetailService.updateBatchById(deliverSkuUpdateList);
    }

}
